import { TILE } from "../enum";
import { MAP } from "../Types";
import { Coord } from "./Coord";

export class Room {
    tiles: Coord[];
    connectedRooms: Room[];
    /** 边界非墙节点 */
    edgeTiles: Coord[];

    min = new Coord(Infinity, Infinity);
    max = new Coord(-1, -1);
    get roomSize() {
        return this.tiles.length;
    }
    private _cache = {
        min: { tileX: Infinity, tileY: Infinity },
        max: { tileX: -1, tileY: -1 },
        center: undefined,
    } as {
        min: { tileX: number; tileY: number };
        max: { tileX: number; tileY: number };
        center?: Coord;
    };
    /** 房间的中心，所以进行了缓存 */
    get center() {
        const cache = this._cache;
        if (
            cache.center &&
            this.min.tileX === cache.min.tileX &&
            this.max.tileX === cache.max.tileX &&
            this.min.tileY === cache.min.tileY &&
            this.max.tileY === cache.max.tileY
        ) {
            return this._cache.center as Coord;
        }
        const result = new Coord(
            (this.min.tileX + this.max.tileX) / 2,
            (this.min.tileY + this.max.tileY) / 2
        );
        this._cache.center = result;
        return result;
    }

    constructor(roomTiles: Coord[], map: MAP) {
        this.tiles = roomTiles;
        this.connectedRooms = [];
        this.edgeTiles = this.tiles.reduce((col: Coord[], tile) => {
            map.$mapCross(tile.tileX, tile.tileY, (value, x, y) => {
                if (!(x === tile.tileX && y === tile.tileY)) {
                    if (value === TILE.Wall) {
                        col.push(tile);
                        this.calcMinMax(tile);
                        return false;
                    }
                }
            });
            return col;
        }, []);
    }
    calcMinMax(tile: Coord) {
        const { tileX, tileY } = tile;
        if (tileX > this.max.tileX) {
            this.max.tileX = tileX;
        } else if (tileX < this.min.tileX) {
            this.min.tileX = tileX;
        }
        if (tileY > this.max.tileY) {
            this.max.tileY = tileY;
        } else if (tileY < this.min.tileY) {
            this.min.tileY = tileY;
        }
    }
    isConnected(otherRoom: Room) {
        return this.connectedRooms.includes(otherRoom);
    }
    static ConnectRooms(roomA: Room, roomB: Room) {
        roomA.connectedRooms.push(roomB);
        roomB.connectedRooms.push(roomA);
    }
}
